/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package controller.commands;

import controller.Constants;
import core.BoxNode;
import core.Node;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import model.graphic.objects.GBoxNode;
import model.graphic.objects.GDispatcher;
import model.graphic.objects.GDispatcherPort;
import model.graphic.objects.GInput;
import model.graphic.objects.GInputPort;
import model.graphic.objects.GOutput;
import model.graphic.objects.GOutputPort;
import model.graphic.objects.GTransmitterNode;
import model.graphic.objects.GTrigger;
import model.graphic.objects.GTriggerPort;
import model.graphic.objects.RectangleGraphical;

/**
 *
 * @author Jelle
 */
public class AddTransmitterCommand extends BasicCommand {

    private String type;
    private String name = null;
    private String ref = null;
    //optional fields needed for directly connecting the 2 ports of the transmitter
    private ArrayList<GDispatcherPort> gdp;
    private ArrayList<GTrigger> triggers;
    private ArrayList<GInputPort> ginp;
    private ArrayList<GOutput> gop;

    public AddTransmitterCommand(String type, String name) {
        this.type = type;
        this.name = name;
    }

    public AddTransmitterCommand(String type, String name,ArrayList<GDispatcherPort> gdp, ArrayList<GTrigger> triggers) {
        this(type,name);
        this.gdp = gdp;
        this.triggers = triggers;
    }

    public AddTransmitterCommand(String type, String name, String ref, ArrayList<GInputPort> ginp, ArrayList<GOutput> gop){
        this(type,name,ref);
        this.ginp = ginp;
        this.gop = gop;
    }

    public AddTransmitterCommand(String type, String name, String ref) {
        this.type = type;
        this.ref = ref;
        this.name = name;
    }

    @Override
    public void execute() {
        if (type.equals(Constants.getTriggerTransmitterInString())) {
            RectangleGraphical rn = (RectangleGraphical) gmodel.getSelected();
            GBoxNode gb = (GBoxNode) rn;
            BoxNode bn = (BoxNode) sync.get(rn);
            GTransmitterNode gn = new GTransmitterNode(gb, true);

            gn.setType(Constants.getTriggerTransmitterInString());
            gn.setName(name);
            GTriggerPort h1 = new GTriggerPort(gn, 30, 40, 15);
            GTrigger c = new GTrigger(h1, 5);
            h1.attach(gn);

            GDispatcherPort h2 = new GDispatcherPort(gn, 30, 40, 15);
            h2.attach(gn);
            GDispatcher d = new GDispatcher(h2);

            if (name != null) {
                h1.setName(name);
                d.setName(name);
                h2.setName(name);
                c.setName(name);
            }

            bn.putTriggerPort(name);
            h1.setBaseColor(rn.getBaseColor());
            h2.setBaseColor(rn.getBaseColor());
            d.setBaseColor(rn.getBaseColor());
            c.setBaseColor(rn.getBaseColor());

            gb.addTransmitterObject(gn);
            gview.add(gn);
            gb.addTransmitterObject(h1);
            gview.add(h1);
            gview.setLayer(h1, 10, 0);
            gb.addTransmitterObject(h2);
            gview.add(h2);
            gview.setLayer(h2, 10, 0);
            gb.addTransmitterObject(d);
            gview.add(d);
            gview.setLayer(d, 10, 0);
            gb.addTransmitterObject(c);
            gview.add(c);
            gview.setLayer(c, 10, 0);
            sync.put((Node) bn.getTransmitterNode(name), gn);
            if(triggers != null && gdp != null){
                for(GDispatcherPort disp : gdp){
                    gview.notifyObservers(new AddConnectionCommand(disp,c));
                }
                for(GTrigger tr : triggers){
                    gview.notifyObservers(new AddConnectionCommand(h2,tr));
                }
            }
        } else if (type.equals(Constants.getValueTransmitterInString())) {
            RectangleGraphical rn = (RectangleGraphical) gmodel.getSelected();
            GBoxNode gb = (GBoxNode) rn;
            BoxNode bn = (BoxNode) sync.get(rn);
            GTransmitterNode gn = new GTransmitterNode(gb, true);
            gn.setType(Constants.getValueTransmitterInString());
            gn.setName(name);
            GInputPort h1 = new GInputPort(gn, 30, 40, 15);
            GInput g = new GInput(h1);

            GOutputPort h2 = new GOutputPort(gn, 30, 40, 15);
            GOutput t = new GOutput(h2);

            if (name != null) {
                h1.setName(name);
                t.setName(name);
                h2.setName(name);
                g.setName(name);
            }
            if (name.equals("outStream")) {
                bn.putInPort(name, PrintStream.class);
            } else {
                Class<?> c = null;
                try {
                    c = Class.forName(ref);
                    gn.setClassDef(ref);
                // System.out.println("cccc"+c.getClass().getSimpleName());
                } catch (ClassNotFoundException ex) {
                    Logger.getLogger(AddAttachmentCommand.class.getName()).log(Level.SEVERE, null, ex);
                }

                //  System.out.println(ref.getSimpleName());

                bn.putInPort(name, c);
            }
            h1.setBaseColor(rn.getBaseColor());
            h2.setBaseColor(rn.getBaseColor());
            t.setBaseColor(rn.getBaseColor());
            g.setBaseColor(rn.getBaseColor());

            gb.addTransmitterObject(gn);
            gview.add(gn);
            gb.addTransmitterObject(h1);
            gview.add(h1);
            gview.setLayer(h1, 10, 0);
            gb.addTransmitterObject(h2);
            gview.add(h2);
            gview.setLayer(h2, 10, 0);
            gb.addTransmitterObject(t);
            gview.add(t);
            gview.setLayer(t, 10, 0);
            gview.setLayer(t, 10, 0);
            gb.addTransmitterObject(g);
            gview.add(g);
            sync.put((Node) bn.getTransmitterNode(name), gn);
            if(ginp != null && gop != null){
                for(GInputPort gin : ginp){
                    gview.notifyObservers(new AddConnectionCommand(t,gin));
                }
                for(GOutput go : gop){
                    gview.notifyObservers(new AddConnectionCommand(go,h1));
                }
            }
        } else if (type.equals(Constants.getTriggerTransmitterOutString())) {
            RectangleGraphical rn = (RectangleGraphical) gmodel.getSelected();
            GBoxNode gb = (GBoxNode) rn;
            BoxNode bn = (BoxNode) sync.get(rn);
            GTransmitterNode gn = new GTransmitterNode(gb, false);
            gn.setType(Constants.getTriggerTransmitterOutString());
            gn.setName(name);
            GDispatcherPort h1 = new GDispatcherPort(gn, 30, 40, 15);
            GDispatcher d = new GDispatcher(h1);
            GTriggerPort h2 = new GTriggerPort(gn, 30, 40, 15);
            GTrigger c = new GTrigger(h2, 5);
            if (name != null) {
                h1.setName(name);
                d.setName(name);
                h2.setName(name);
                c.setName(name);
            }
            bn.putDispatcherPort(name);
            h1.setBaseColor(rn.getBaseColor());
            h2.setBaseColor(rn.getBaseColor());
            d.setBaseColor(rn.getBaseColor());
            c.setBaseColor(rn.getBaseColor());

            gb.addTransmitterObject(gn);
            gview.add(gn);
            gb.addTransmitterObject(h1);
            gview.add(h1);
            gview.setLayer(h1, 10, 0);
            gb.addTransmitterObject(h2);
            gview.add(h2);
            gview.setLayer(h2, 10, 0);
            gb.addTransmitterObject(d);
            gview.add(d);
            gview.setLayer(d, 10, 0);
            gb.addTransmitterObject(c);
            gview.add(c);
            gview.setLayer(c, 10, 0);
            sync.put((Node) bn.getTransmitterNode(name), gn);
            if(triggers != null && gdp != null){
                for(GDispatcherPort disp : gdp){
                    gview.notifyObservers(new AddConnectionCommand(disp,c));
                }
                for(GTrigger tr : triggers){
                    gview.notifyObservers(new AddConnectionCommand(h1,tr));
                }
            }
        } else if (type.equals(Constants.getValueTransmitterOutString())) {
            RectangleGraphical rn = (RectangleGraphical) gmodel.getSelected();
            GBoxNode gb = (GBoxNode) rn;
            BoxNode bn = (BoxNode) sync.get(rn);
            GTransmitterNode gn = new GTransmitterNode(gb, false);
            gn.setType(Constants.getValueTransmitterOutString());
            gn.setName(name);
            GOutputPort h1 = new GOutputPort(gn, 30, 40, 15);
            GOutput t = new GOutput(h1);
            GInputPort h2 = new GInputPort(gn, 30, 40, 15);
            GInput g = new GInput(h2);

            if (name != null) {
                h1.setName(name);
                t.setName(name);
                h2.setName(name);
                g.setName(name);
            }
            Class<?> c = null;
            try {
                c = Class.forName(ref);
                gn.setClassDef(ref);
            // System.out.println("cccc"+c.getClass().getSimpleName());
            } catch (ClassNotFoundException ex) {
                Logger.getLogger(AddAttachmentCommand.class.getName()).log(Level.SEVERE, null, ex);
            }
            bn.putOutPort(name, c);
            h1.setBaseColor(rn.getBaseColor());
            h2.setBaseColor(rn.getBaseColor());
            t.setBaseColor(rn.getBaseColor());
            g.setBaseColor(rn.getBaseColor());

            gb.addTransmitterObject(gn);
            gview.add(gn);
            gb.addTransmitterObject(h1);
            gview.add(h1);
            gview.setLayer(h1, 10, 0);
            gb.addTransmitterObject(h2);
            gview.add(h2);
            gview.setLayer(h2, 10, 0);
            gb.addTransmitterObject(t);
            gview.add(t);
            gview.setLayer(t, 10, 0);
            gb.addTransmitterObject(g);
            gview.add(g);
            gview.setLayer(g, 10, 0);
            sync.put((Node) bn.getTransmitterNode(name), gn);
            if(ginp != null && gop != null){
                for(GInputPort gin : ginp){
                    gview.notifyObservers(new AddConnectionCommand(t,gin));
                }
                for(GOutput go : gop){
                    gview.notifyObservers(new AddConnectionCommand(go,h2));
                }
            }
        }
    }
}